package com.orange.cetback.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.orange.cetback.common.context.BaseContext;
import com.orange.cetback.common.enums.MaterialType;
import com.orange.cetback.common.properties.YoudaoProperties;
import com.orange.cetback.common.utils.AuthV3Util;
import com.orange.cetback.common.utils.HttpUtil;
import com.orange.cetback.common.vo.PageResult;
import com.orange.cetback.pojo.dto.AnswerRecordDTO;
import com.orange.cetback.pojo.dto.UserAnswerRecordDTO;
import com.orange.cetback.pojo.dto.WritingDTO;
import com.orange.cetback.pojo.entity.Questions;
import com.orange.cetback.pojo.entity.UserAnswerRecord;
import com.orange.cetback.mapper.UserAnswerRecordMapper;
import com.orange.cetback.pojo.entity.UserAnswers;
import com.orange.cetback.pojo.entity.WritingCorrection;
import com.orange.cetback.pojo.vo.UserAnswerRecordVO;
import com.orange.cetback.service.UserAnswerRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orange.cetback.service.UserAnswersService;
import com.orange.cetback.service.WritingCorrectionService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author chenenjun
 * @since 2025-03-05
 */
@Service
public class UserAnswerRecordServiceImpl extends ServiceImpl<UserAnswerRecordMapper, UserAnswerRecord> implements UserAnswerRecordService {

    @Autowired
    private YoudaoProperties youdaoProperties;

    @Autowired
    private QuestionsServiceImpl questionsService;
    @Autowired
    private UserAnswersService userAnswersService;
    @Autowired
    private WritingCorrectionService writingCorrectionService;
    @Autowired
    private ExamPapersServiceImpl examPapersService;


    @Override
    public UserAnswerRecord saveUserAnswerRecord(UserAnswerRecordDTO userAnswerRecordDTO) {
        UserAnswerRecord userAnswerRecord = new UserAnswerRecord();
        BeanUtils.copyProperties(userAnswerRecordDTO, userAnswerRecord);
        userAnswerRecord.setUserId(BaseContext.getCurrentId());
        userAnswerRecord.setSubmitTime(LocalDateTime.now());
        if (userAnswerRecord.getMaterialType().equals(MaterialType.WRITING.name())){
            UserAnswers userAnswers = userAnswerRecordDTO.getUserAnswersList().get(0);
            Questions questions = questionsService.getById(userAnswers.getQuestionId());
            WritingDTO writingDTO = new WritingDTO();
            writingDTO.setGrade("cet4");
            writingDTO.setModelContent(questions.getAnswer());
            writingDTO.setContent(userAnswers.getUserAnswer());
            writingDTO.setCorrectVersion("advanced");
            writingDTO.setIsNeedSynonyms("false");
            writingDTO.setIsNeedEssayReport("true");
            WritingCorrection writingCorrection = writingCorrection(writingDTO);
            userAnswers.setScore(writingCorrection.getTotalScore());
            userAnswerRecord.setTotalScore(writingCorrection.getTotalScore());
            this.baseMapper.insert(userAnswerRecord);
            userAnswers.setRecordId(userAnswerRecord.getRecordId());
            writingCorrection.setRecordId(userAnswerRecord.getRecordId());
            userAnswersService.save(userAnswers);
            writingCorrectionService.save(writingCorrection);
        }else {
            this.baseMapper.insert(userAnswerRecord);
            userAnswerRecordDTO.getUserAnswersList().forEach(userAnswers -> {
                userAnswers.setRecordId(userAnswerRecord.getRecordId());
                userAnswersService.save(userAnswers);
            });
        }

        return userAnswerRecord;
    }

    @Override
    public UserAnswerRecordVO getAnswerRecord(Long recordId) {
        UserAnswerRecord userAnswerRecord = this.baseMapper.selectById(recordId);
        UserAnswerRecordVO userAnswerRecordVO = new UserAnswerRecordVO();
        BeanUtils.copyProperties(userAnswerRecord, userAnswerRecordVO);
        userAnswerRecordVO.setUserAnswersList(userAnswersService.getUserAnswersByRecordId(recordId));
        if (userAnswerRecord.getMaterialType().equals(MaterialType.WRITING.name())){
            userAnswerRecordVO.setWritingCorrection(writingCorrectionService.getWritingCorrectionByRecordId(recordId));
        }

        return userAnswerRecordVO;
    }

    @Override
    public PageResult<UserAnswerRecordVO> pageQuery(AnswerRecordDTO answerRecordDTO) {
        Page<UserAnswerRecord> page = new Page<>(answerRecordDTO.getPageNum(), answerRecordDTO.getPageSize());
        LambdaQueryWrapper<UserAnswerRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserAnswerRecord::getUserId, BaseContext.getCurrentId());
        queryWrapper.orderByDesc(UserAnswerRecord::getSubmitTime);
        page = this.baseMapper.selectPage(page, queryWrapper);
        List<UserAnswerRecord> records = page.getRecords();
        List<UserAnswerRecordVO> userAnswerRecordVOS = records.stream().map(userAnswerRecord -> {
            UserAnswerRecordVO userAnswerRecordVO = new UserAnswerRecordVO();
            BeanUtils.copyProperties(userAnswerRecord, userAnswerRecordVO);
            userAnswerRecordVO.setUserAnswersList(userAnswersService.getUserAnswersByRecordId(userAnswerRecord.getRecordId()));
            userAnswerRecordVO.setExamPapers(examPapersService.getById(userAnswerRecord.getPaperId()));
            return userAnswerRecordVO;
        }).toList();
        return new PageResult<>(page.getTotal(),userAnswerRecordVOS);
    }


    private WritingCorrection writingCorrection(WritingDTO writingDTO){
        // 添加请求参数
        Map<String, String[]> params = createRequestParams(writingDTO);
        // 添加鉴权相关参数
        try {
            AuthV3Util.addAuthParams(youdaoProperties.getAppKey(), youdaoProperties.getAppSecret(), params);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        byte[] result = HttpUtil.doPost(youdaoProperties.getUrl(), null, params, "application/json");
        String responseJson = new String(result, StandardCharsets.UTF_8);
        // 使用 Jackson 解析 JSON 字符串
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JsonNode rootNode = objectMapper.readTree(responseJson);
            JsonNode resultNode = rootNode.path("Result");
            JsonNode majorScore = resultNode.path("majorScore");
            // 提取所需的字段
            String essayAdvice = resultNode.path("essayAdvice").asText();
            BigDecimal totalScore = resultNode.path("totalScore").decimalValue();
            String totalEvaluation = resultNode.path("totalEvaluation").asText();
            BigDecimal fullScore = resultNode.path("fullScore").decimalValue();
            BigDecimal grammarScore = majorScore.path("grammarScore").decimalValue();
            String grammarAdvice = majorScore.path("grammarAdvice").asText();
            BigDecimal topicScore = majorScore.path("topicScore").decimalValue();
            BigDecimal wordScore = majorScore.path("wordScore").decimalValue();
            String wordAdvice = majorScore.path("wordAdvice").asText();
            BigDecimal structureScore = majorScore.path("structureScore").decimalValue();
            String structureAdvice = majorScore.path("structureAdvice").asText();
            WritingCorrection writingCorrection = WritingCorrection.builder()
                    .essayAdvice(essayAdvice)
                    .totalScore(totalScore)
                    .totalEvaluation(totalEvaluation)
                    .fullScore(fullScore)
                    .grammarScore(grammarScore)
                    .grammarAdvice(grammarAdvice)
                    .topicScore(topicScore)
                    .wordScore(wordScore)
                    .wordAdvice(wordAdvice)
                    .structureScore(structureScore)
                    .structureAdvice(structureAdvice)
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
            return writingCorrection;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    private static Map<String, String[]> createRequestParams(WritingDTO writingDTO) {
        return new HashMap<String, String[]>() {{
            put("q", new String[]{writingDTO.getContent()});
            put("grade", new String[]{writingDTO.getGrade()});
            put("modelContent", new String[]{writingDTO.getModelContent()});
            put("isNeedSynonyms", new String[]{writingDTO.getIsNeedSynonyms()});
            put("correctVersion", new String[]{writingDTO.getCorrectVersion()});
            put("isNeedEssayReport", new String[]{writingDTO.getIsNeedEssayReport()});
        }};
    }
}
